﻿using ScottPlot.Avalonia;
using Digitalmes.Core.Common.Interfaces;
using Digitalmes.Core.Messages;
using Digitalmes.Core.Services;
using Digitalmes.Core.Domain.Eitites;

namespace Digitalmes.AvaloniaUI.ViewModels;

/// <summary>
/// 工作台（主页面）
/// </summary>
[VmSingletontLifeTime]
public sealed partial class WorkbenchViewModel : ViewModelBase, IDisposable
{
    private readonly CancellationTokenSource _cts = new();

    private readonly IMessageQueue<TurntableArchiveMessage> _archiveMQ;
    private readonly IMessageQueue<TurntableRealtimeMessage> _realtimeMQ;
    private readonly IParamStandardService _paramStandardService;

    /// <summary>
    /// 日志消息
    /// </summary>
    [ObservableProperty]
    public partial ObservableCollection<string> MessageLogs { get; set; } = [];

    /// <summary>
    /// 正转时间图
    /// </summary>
    public AvaPlot PlotForwardRotationTime { get; }

    /// <summary>
    /// 反转时间图
    /// </summary>
    public AvaPlot PlotReverseRotationTime { get; }

    /// <summary>
    /// 重复定位精度A图
    /// </summary>
    public AvaPlot PlotRepeatabilityA { get; }

    /// <summary>
    /// 重复定位精度B图
    /// </summary>
    public AvaPlot PlotRepeatabilityB { get; }

    /// <summary>
    /// 轴向重复定位精度
    /// </summary>
    public AvaPlot PlotRepeatabilityAxialA { get; }

    /// <summary>
    /// 轴向重复定位精度（偏载）
    /// </summary>
    public AvaPlot PlotRepeatabilityAxialB { get; }

    /// <summary>
    /// 转速
    /// </summary>
    public AvaPlot PlotRotationalSpeed { get; }

    public WorkbenchViewModel(IMessageQueue<TurntableArchiveMessage> archiveMQ,
        IMessageQueue<TurntableRealtimeMessage> realtimeMQ,
        IParamStandardService paramStandardService)
    {
        _archiveMQ = archiveMQ;
        _realtimeMQ = realtimeMQ;
        _paramStandardService = paramStandardService;

        PlotForwardRotationTime = new AvaPlot();
        PlotForwardRotationTime.Plot.Font.Automatic();

        PlotReverseRotationTime = new AvaPlot();
        PlotReverseRotationTime.Plot.Font.Automatic();

        PlotRepeatabilityA = new AvaPlot();
        PlotRepeatabilityA.Plot.Font.Automatic();
        
        PlotRepeatabilityB = new AvaPlot();
        PlotRepeatabilityB.Plot.Font.Automatic();

        PlotRepeatabilityAxialA = new AvaPlot();
        PlotRepeatabilityAxialA.Plot.Font.Automatic();

        PlotRepeatabilityAxialB = new AvaPlot();
        PlotRepeatabilityAxialB.Plot.Font.Automatic();

        PlotRotationalSpeed = new AvaPlot();
        PlotRotationalSpeed.Plot.Font.Automatic();

        Polling().Wait();
    }

    async Task Polling()
    {
        var limitLineColor = ScottPlot.Color.FromColor(System.Drawing.Color.Red);

        var (okA, minA, maxA) = await _paramStandardService.GetStandardAsync("repeatability_A");
        if (okA)
        {
            PlotRepeatabilityA.Plot.Add.HorizontalLine(minA!.Value, width: 1, color: limitLineColor); // 下限线
            PlotRepeatabilityA.Plot.Add.HorizontalLine(maxA!.Value, width: 1, color: limitLineColor); // 上限线
        }

        var (okB, minB, maxB) = await _paramStandardService.GetStandardAsync("repeatability_B");
        if (okB)
        {
            PlotRepeatabilityB.Plot.Add.HorizontalLine(minB!.Value, width: 1, color: limitLineColor); // 下限线
            PlotRepeatabilityB.Plot.Add.HorizontalLine(maxB!.Value, width: 1, color: limitLineColor); // 上限线
        }

        var (okAxialA, minAxialA, maxAxialA) = await _paramStandardService.GetStandardAsync("repeatability_axial_A");
        if (okAxialA)
        {
            PlotRepeatabilityAxialA.Plot.Add.HorizontalLine(minAxialA!.Value, width: 1, color: limitLineColor); // 下限线
            PlotRepeatabilityAxialA.Plot.Add.HorizontalLine(maxAxialA!.Value, width: 1, color: limitLineColor); // 上限线
        }

        var (okAxialB, minAxialB, maxAxialB) = await _paramStandardService.GetStandardAsync("repeatability_axial_B");
        if (okAxialB)
        {
            PlotRepeatabilityAxialB.Plot.Add.HorizontalLine(minAxialB!.Value, width: 1, color: limitLineColor); // 下限线
            PlotRepeatabilityAxialB.Plot.Add.HorizontalLine(maxAxialB!.Value, width: 1, color: limitLineColor); // 上限线
        }

        var streamForwardRotationTime = PlotForwardRotationTime.Plot.Add.DataStreamer(32);
        streamForwardRotationTime.ViewScrollLeft();
        PlotForwardRotationTime.UserInputProcessor.Disable();

        var streamReverseRotationTime = PlotReverseRotationTime.Plot.Add.DataStreamer(32);
        streamReverseRotationTime.ViewScrollLeft();
        PlotReverseRotationTime.UserInputProcessor.Disable();

        var streamRepeatabilityA = PlotRepeatabilityA.Plot.Add.DataStreamer(32);
        streamRepeatabilityA.ViewScrollLeft();
        PlotRepeatabilityA.UserInputProcessor.Disable();

        var streamRepeatabilityB = PlotRepeatabilityB.Plot.Add.DataStreamer(32);
        streamRepeatabilityB.ViewScrollLeft();
        PlotRepeatabilityB.UserInputProcessor.Disable();

        var streamRepeatabilityAxialA = PlotRepeatabilityAxialA.Plot.Add.DataStreamer(32);
        streamRepeatabilityAxialA.ViewScrollLeft();
        PlotRepeatabilityAxialA.UserInputProcessor.Disable();

        var streamRepeatabilityAxialB = PlotRepeatabilityAxialB.Plot.Add.DataStreamer(32);
        streamRepeatabilityAxialB.ViewScrollLeft();
        PlotRepeatabilityAxialB.UserInputProcessor.Disable();

        // 转速
        var streamRotationalSpeed = PlotRotationalSpeed.Plot.Add.DataStreamer(128);
        streamRotationalSpeed.ViewScrollLeft();
        PlotRotationalSpeed.UserInputProcessor.Disable();

        // 存档数据接收
        _ = Task.Run(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                var message = await _archiveMQ.DequeueAsync().ConfigureAwait(false);
                if (message.Rotation is Rotation.Forward)
                {
                    streamForwardRotationTime.Add(message.ForwardRotationTime);
                    streamRepeatabilityA.Add(message.RepeatabilityA);
                    streamRepeatabilityAxialA.Add(message.RepeatabilityAxialA);
                    streamRepeatabilityAxialB.Add(message.RepeatabilityAxialB); // 轴向都是正转
                }
                else if (message.Rotation is Rotation.Reverse)
                {
                    streamReverseRotationTime.Add(message.ReverseRotationTime);
                    streamRepeatabilityB.Add(message.RepeatabilityB);
                }

                // 日志显示
                AddLog(message);
            }
        });

        // 存档数据刷新图表
        _ = Task.Run(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                await Task.Delay(1_000).ConfigureAwait(false);

                if (streamForwardRotationTime.HasNewData)
                {
                    PlotForwardRotationTime.Refresh();
                }
                if (streamReverseRotationTime.HasNewData)
                {
                    PlotReverseRotationTime.Refresh();
                }
                if (streamRepeatabilityA.HasNewData)
                {
                    PlotRepeatabilityA.Refresh();
                }
                if (streamRepeatabilityB.HasNewData)
                {
                    PlotRepeatabilityB.Refresh();
                }
                if (streamRepeatabilityAxialA.HasNewData)
                {
                    PlotRepeatabilityAxialA.Refresh();
                }
                if (streamRepeatabilityAxialB.HasNewData)
                {
                    PlotRepeatabilityAxialB.Refresh();
                }
            }
        });

        // 实时数据接收
        _ = Task.Run(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                var message = await _realtimeMQ.DequeueAsync().ConfigureAwait(false);
                streamRotationalSpeed.Add(message.RotationalSpeed);

                // 不显示日志
            }
        });

        // 实时数据刷新图表
        _ = Task.Run(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                await Task.Delay(300).ConfigureAwait(false);
                if (streamRotationalSpeed.HasNewData)
                {
                    PlotRotationalSpeed.Refresh();
                }
            }
        });

        // test
        //{
        //    ScottPlot.DataGenerators.RandomWalker walker1 = new(0);
        //    ScottPlot.DataGenerators.RandomWalker walker2 = new(1);
        //    ScottPlot.DataGenerators.RandomWalker walker3 = new(2);
        //    ScottPlot.DataGenerators.RandomWalker walker4 = new(3);
        //    ScottPlot.DataGenerators.RandomWalker walker5 = new(5);
        //    ScottPlot.DataGenerators.RandomWalker walker6 = new(6);
        //    _ = Task.Run(async () =>
        //    {
        //        Rotation rotation = Rotation.Forward;
        //        while (!_cts.IsCancellationRequested)
        //        {
        //            await Task.Delay(1_000).ConfigureAwait(false);

        //            rotation = rotation is not Rotation.Forward ? Rotation.Forward : Rotation.Reverse;
        //            await _archiveMQ.EnqueueAsync(new TurntableArchiveMessage(
        //                Math.Round(walker1.Next(), 3),
        //                Math.Round(walker2.Next(), 3),
        //                Math.Round(walker3.Next(), 3), 
        //                Math.Round(walker4.Next(), 3),
        //                Math.Round(walker5.Next(), 3),
        //                Math.Round(walker6.Next(), 3),
        //                rotation)).ConfigureAwait(false);
        //        }
        //    });

        //    _ = Task.Run(async () =>
        //    {
        //        while (!_cts.IsCancellationRequested)
        //        {
        //            await Task.Delay(300).ConfigureAwait(false);

        //            await _realtimeMQ.EnqueueAsync(new TurntableRealtimeMessage(walker1.Next())).ConfigureAwait(false);
        //        }
        //    });
        //}
    }

    private void AddLog(TurntableArchiveMessage? message)
    {
        if (message == null)
        {
            return;
        }

        if (MessageLogs.Count > 16)
        {
            MessageLogs.RemoveAt(MessageLogs.Count - 1);
        }

        var msg = $"{DateTime.Now:MM/dd HH:mm:ss}\t" +
            $"正转时间：{message.ForwardRotationTime}s，" +
            $"反转时间：{message.ReverseRotationTime}s，" +
            $"重复定位精度-0：{message.RepeatabilityA}mm，" +
            $"重复定位精度-180：{message.RepeatabilityB}mm，" +
            $"轴向重复定位精度：{message.RepeatabilityAxialA}mm，" +
            $"轴向重复定位精度（偏载）：{message.RepeatabilityAxialB}mm";
        MessageLogs.Insert(0, msg);
    }

    public void Dispose()
    {
        _cts.Cancel();
    }
}
